package com.example.wechattakeaway.security;

import com.example.wechattakeaway.security.relam.SysModularRealmAuthenticator;
import com.example.wechattakeaway.security.relam.UserRealm;
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
import org.apache.shiro.authc.pam.ModularRealmAuthenticator;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Configuration
public class ShiroConfig {

    /**
     *创建ShiroFilterFactoryBean
     * @param securityManager（导入securityManager的Bean）
     */
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") SecurityManager securityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        //设置安全管理器
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        //设置Shiro内置过滤器
        /*
         *Shiro内置过滤器，可以实现权限相关的拦截器
         *    常用的过滤器：
         *        anon: 无需认证（登录）可以访问
         *        authc: 必须认证（登录）才可以访问
         *        user: 如果使用rememberMe的功能可以直接访问
         *        perms: 该资源必须得到资源权限才可以访问
         *        role: 该资源必须得到角色资源才可以访问
         */
        Map<String,String> filterMap = new LinkedHashMap<String, String>();
//        Map<String,String> filterMap = new HashMap<String, String>();

//        filterMap.put("/*","authc");
        filterMap.put ("/user/updatePassword","authc");

        //修改调整的登录页面
        shiroFilterFactoryBean.setLoginUrl("/shiro/toLogin");
        shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);

        return shiroFilterFactoryBean;
    }

    /**
     * 创建DefaultWebSecurityManager(SecurityManager)
     * @param userRealm(导入useRealm的Bean)
     */
    @Bean(name = "securityManager")
    public SecurityManager getSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //将自定义的Realms注册到安全管理器当中
        securityManager.setAuthenticator(modularRealmAuthenticator());
        List<Realm> realms = new ArrayList<>();
        realms.add (userRealm);
        securityManager.setRealms (realms);
        //将自定义的会话管理器注册到安全管理器当中
        securityManager.setSessionManager (sessionManager ());
        //将自定义的redis缓存管理器注册到安全管理器当中
        securityManager.setCacheManager (cacheManager());

        return securityManager;
    }


    @Value("${spring.redis.host}")
    private String host;
    @Value("${spring.redis.port}")
    private int port;
    @Value("${spring.redis.password}")
    private String password;


    /**
     * 1.redis控制器，操作redis
     * @return
     */
    public RedisManager redisManager(){
        RedisManager redisManager = new RedisManager ();
        redisManager.setHost (host);
        redisManager.setPort (port);
        redisManager.setPassword (password);
        return redisManager;
    }

    /**
     * 2.sessionDao
     * @return
     */
    public RedisSessionDAO redisSessionDAO(){
        RedisSessionDAO redisSessionDAO = new RedisSessionDAO ();
        redisSessionDAO.setRedisManager (redisManager ());
        return redisSessionDAO;
    }

    /**
     * 3.会话管理器
     * @return
     */
    public DefaultWebSessionManager sessionManager(){
        CustomSessionManager sessionManager = new CustomSessionManager ();
        sessionManager.setSessionDAO (redisSessionDAO ());
        return sessionManager;
    }

    /**
     * 4.缓存管理器
     * @return
     */
    public RedisCacheManager cacheManager(){
        RedisCacheManager cacheManager = new RedisCacheManager ();
        cacheManager.setRedisManager (redisManager ());
        return cacheManager;
    }


    @Bean
    public ModularRealmAuthenticator modularRealmAuthenticator(){
        //自己重写的ModularRealmAuthenticator
        SysModularRealmAuthenticator modularRealmAuthenticator = new SysModularRealmAuthenticator ();
        modularRealmAuthenticator.setAuthenticationStrategy(new AtLeastOneSuccessfulStrategy());
        return modularRealmAuthenticator;
    }

    /**
     * 创建Realm
     */
    @Bean(name = "userRealm")
    public UserRealm getUserRealm(){
        return new UserRealm();
    }


    //配置shiro对注解的支持
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager")SecurityManager securityManager){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor ();
        advisor.setSecurityManager (securityManager);
        return  advisor;
    }
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;

    }

}